/*
 * @Description: 签名工具方法
 * @Author: Haor
 * @Date: 2022-05-07 13:50:59
 * @LastEditTime: 2022-05-09 16:49:06
 * @LastEditors: Haor
 */
import * as crypto from 'crypto'

/**
 * 签名参数
 */
export interface SignParams {
	// appid
	appId: string | number

	// 随机时间戳
	timestamp: string

	// 随机数字
	nonce: number
}

export class SignUtil {
    /**
     *
     * @param {Object} params 业务参数
     * @param {SignParams} signParams 签名参数
     */
	constructor(params: any, signParams: SignParams) {
		this.signStr = this.genSign(params, signParams)
	}

	// 签名好的字符串
	signStr = ''

	/**
	 * 获取签名
	 * @returns
	 */
	public getSign(): string {
		return this.signStr
	}

	/**
	 * 生成签名
	 * @param params
	 * @param signParams
	 * @returns
	 */
	genSign(params, signParams: SignParams): string {
		const signStr = this.foramtParams(params, signParams)
        console.log('签名原始数据：', signStr)
		const md5SignStr = this.getEncrypt(signStr).toUpperCase()
		return md5SignStr
	}

	/**
	 * 验证签名
	 * @param signStr
	 * @return {Boolean}
	 */
	validate(signStr: string): boolean {
		return this.signStr === signStr
	}


	/**
	 * 获取加密字符串
	 * @param {String} str
	 * @return {String}
	 */
	private getEncrypt(str: string): string {
		return crypto.createHash('md5').update(String(str), 'utf8').digest('hex')
	}

	/**
	 * 格式化签名参数
	 * @param params 获去签名参数
	 * @param signParams 签名参数信息
	 * @return {String}
	 */
	private foramtParams(params={}, signParams: SignParams): string {
		let signStr = ''
		const mergeParasm = { ...params, ...signParams }
		const paramKeys = Object.keys(params).sort().concat(['appId', 'timestamp', 'nonce'])
		for (let i = 0; i < paramKeys.length; i++) {
			const key = paramKeys[i]
			signStr += `${key}=${mergeParasm[key]}`
		}
		return signStr
	}
}
